package cn.mujiankeji.mbrowser.功能.播放框.核心

import android.annotation.SuppressLint
import android.content.Context
import androidx.media3.common.C
import androidx.media3.common.PlaybackException
import androidx.media3.common.Player
import androidx.media3.common.TrackSelectionOverride
import androidx.media3.exoplayer.DefaultLoadControl
import androidx.media3.exoplayer.ExoPlayer
import cn.mujiankeji.mbrowser.功能.播放框.模型.播放状态枚举
import cn.mujiankeji.mbrowser.功能.播放框.模型.播放文件信息
import cn.mujiankeji.mbrowser.功能.播放框.模型.音轨信息
import cn.mujiankeji.mbrowser.功能.播放框.模型.字幕信息
import cn.mujiankeji.mbrowser.工具.mlog
import kotlinx.coroutines.Job
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow

@SuppressLint("UnsafeOptInUsageError")
class ExoPlayer(
    val context : Context,
    val helper : ExoHelper = ExoHelper(context),
    val 错误回调 : ((错误: String, 异常: Exception?) -> Unit) ?= null,
) : PlayerInterface {

    // 播放器当前状态
    private val _播放状态 = MutableStateFlow(播放状态枚举.初始化)
    override val 播放状态: StateFlow<播放状态枚举> = _播放状态.asStateFlow()

    // 当前播放进度(毫秒)
    private val _当前进度 = MutableStateFlow(0L)
    override val 当前进度: StateFlow<Long> = _当前进度.asStateFlow()

    // 视频总时长(毫秒)
    private val _总时长 = MutableStateFlow(0L)
    override val 总时长: StateFlow<Long> = _总时长.asStateFlow()

    // 缓冲进度百分比(0-100)
    private val _缓冲进度 = MutableStateFlow(0)
    override val 缓冲进度: StateFlow<Int> = _缓冲进度.asStateFlow()

    // 当前播放速率
    private val _播放速率 = MutableStateFlow(1.0f)
    override val 播放速率: StateFlow<Float> = _播放速率.asStateFlow()

    // 是否静音
    private val _是否静音 = MutableStateFlow(false)
    override val 是否静音: StateFlow<Boolean> = _是否静音.asStateFlow()

    // 当前视频信息
    private val _视频信息 = MutableStateFlow<播放文件信息?>(null)
    override val 视频信息: StateFlow<播放文件信息?> = _视频信息.asStateFlow()


    // 播放器实例
    var 播放器: ExoPlayer? = null
        private set

    // 进度更新任务
    private var 进度更新任务: Job? = null
    suspend fun 更新进度(){
        val player = 播放器 ?: return
        while (true) {
            _当前进度.value = player.currentPosition
            _总时长.value = player.duration.takeIf { it != C.TIME_UNSET } ?: 0L
            _缓冲进度.value = player.bufferedPercentage
            kotlinx.coroutines.delay(500)
        }
    }
    init {
        初始化播放器()
    }

    private fun 初始化播放器(){
        // 创建加载控制器
        val 加载控制器 = DefaultLoadControl.Builder()
            .setBufferDurationsMs(
                15000,    // 最小缓冲时间 (从5秒增加到15秒)
                60000,    // 最大缓冲时间 (从25秒增加到60秒)
                2500,     // 开始播放所需缓冲 (从1.5秒增加到2.5秒)
                5000      // 重新缓冲后开始播放所需缓冲 (从3秒增加到5秒)
            )
            .setPrioritizeTimeOverSizeThresholds(true)
            .setBackBuffer(30000, true)  // 回退缓冲，允许快速回退 (从10秒增加到30秒)
            .build()


        // 创建ExoPlayer实例
        播放器 = ExoPlayer.Builder(context)
            .setLoadControl(加载控制器)
            .build().apply {
                // 添加播放器事件监听
                addListener(object : Player.Listener {
                    override fun onPlaybackStateChanged(state: Int) {
                        when (state) {
                            Player.STATE_IDLE -> 更新播放状态(播放状态枚举.初始化)
                            Player.STATE_BUFFERING -> 更新播放状态(播放状态枚举.加载中)
                            Player.STATE_READY -> {
                                if (isPlaying) {
                                    更新播放状态(播放状态枚举.播放中)
                                } else {
                                    更新播放状态(播放状态枚举.准备完成)
                                }
                                _视频信息.value = _视频信息.value?:播放文件信息().copy(
                                    标题 = mediaMetadata.title?.toString(),
                                    作者 = mediaMetadata.artist?.toString(),
                                    描述 = mediaMetadata.description?.toString(),
                                    宽度 = videoSize.width,
                                    高度 = videoSize.height,
                                    时长 = duration.takeIf { it != C.TIME_UNSET }
                                        ?: 0L,
                                    比特率 = 0, // ExoPlayer不直接提供比特率
                                    帧率 = 0f,  // ExoPlayer不直接提供帧率
                                )

                            }
                            Player.STATE_ENDED -> 更新播放状态(播放状态枚举.已完成)
                        }
                    }

                    override fun onPlayerError(error: PlaybackException) {
                        报告错误("播放错误: ${error.message}", error)
                    }

                    override fun onIsPlayingChanged(isPlaying: Boolean) {
                        if (isPlaying) {
                            更新播放状态(播放状态枚举.播放中)
                        } else if (playbackState == Player.STATE_READY) {
                            更新播放状态(播放状态枚举.已暂停)
                        }
                    }

                    override fun onVideoSizeChanged(videoSize: androidx.media3.common.VideoSize) {
                        val 宽度 = videoSize.width
                        val 高度 = videoSize.height
                        // 更新视频信息
                        _视频信息.value = _视频信息.value?.copy(宽度 = 宽度, 高度 = 高度)
                    }
                })
            }

    }

    override fun 设置视频源(地址 : String,起始位置 : Long,协议头 : Map<String,String>?,自动播放 : Boolean){
        try {
            // 更新播放信息
            _视频信息.value = (_视频信息.value?:播放文件信息()).copy(地址 = 地址, 协议头 = 协议头)

            // 更新状态为加载中
            更新播放状态(播放状态枚举.加载中)

            // 重置播放器
            播放器?.stop()
            _当前进度.value = 0

            播放器?.setMediaSource(helper.创建媒体源(地址,协议头))
            播放器?.prepare()

            if (起始位置 != 0L) 播放器?.seekTo(起始位置)
            if (自动播放) 播放()
        }
        catch (e: Exception) {
            报告错误("加载视频失败: ${e.message}", e)
        }
    }
    fun 播放(来源 : 播放文件信息,起始位置 : Long = 0) {
        设置视频源(地址 = 来源.地址,起始位置,来源.协议头,true)
    }

    override fun 播放() {
        if (播放状态.value == 播放状态枚举.播放中) return
        try {
            播放器?.play()
        } catch (e: Exception) {
            报告错误("播放失败: ${e.message}", e)
        }
    }

    override fun 暂停() {
        if (播放状态.value != 播放状态枚举.播放中) return

        try {
            播放器?.pause()
        } catch (e: Exception) {
            报告错误("暂停失败: ${e.message}", e)
        }
    }

    override fun 停止() {
        try {
            播放器?.stop()
            _当前进度.value = 0
        } catch (e: Exception) {
            报告错误("停止失败: ${e.message}", e)
        }
    }

    fun 释放(){
        try {
            播放器?.stop()
            播放器?.release()
        }catch (_ : Exception){

        }
    }

    override fun 跳转(位置: Long) {
        try {
            播放器?.seekTo(位置)
            _当前进度.value = 位置
        } catch (e: Exception) {
            报告错误("跳转失败: ${e.message}", e)
        }
    }

    /**
     * 设置播放速率
     * @param 速率 播放速率(0.5-2.0)
     */
    override fun 设置播放速率(速率: Float) {
        if (速率 < 0.5f || 速率 > 5.0f) return

        try {
            播放器?.setPlaybackSpeed(速率)
            _播放速率.value = 速率
        } catch (e: Exception) {
            报告错误("设置播放速率失败: ${e.message}", e)
        }
    }

    override fun 设置音量(音量: Float) {
        if (音量 < 0f || 音量 > 1.0f) return

        try {
            播放器?.volume = 音量

            if (音量 == 0f) {
                _是否静音.value = true
            } else if (_是否静音.value) {
                _是否静音.value = false
            }
        } catch (e: Exception) {
            报告错误("设置音量失败: ${e.message}", e)
        }
    }

    override fun 设置静音(静音: Boolean) {
        try {
            if (静音) {
                播放器?.volume = 0f
            } else {
                播放器?.volume = 1f
            }

            _是否静音.value = 静音
        } catch (e: Exception) {
            报告错误("设置静音失败: ${e.message}", e)
        }
    }


    /**
     * 更新播放状态并通知回调
     */
    private fun 更新播放状态(新状态: 播放状态枚举) {
        _播放状态.value = 新状态
    }


    fun 报告错误(错误信息: String, 异常: Exception? = null) {
        更新播放状态(播放状态枚举.错误)
        mlog("播放器错误",错误信息)
        异常?.printStackTrace()
        错误回调?.invoke(错误信息,异常)
    }

    override fun 获取可用音轨(): List<音轨信息> {
        val 结果 = mutableListOf<音轨信息>()
        val 播放器实例 = 播放器 ?: return 结果
        val 轨道信息 = 播放器实例.currentTracks
        轨道信息.groups.forEachIndexed { 组索引, 分组 ->
            if (分组.type == C.TRACK_TYPE_AUDIO) {
                分组.mediaTrackGroup?.let { 媒体分组 ->
                    for (轨索引 in 0 until 媒体分组.length) {
                        val 格式 = 媒体分组.getFormat(轨索引)
                        结果.add(
                            音轨信息(
                                组索引 = 组索引,
                                轨索引 = 轨索引,
                                标签 = 格式.label ?: 格式.language ?: "音轨$轨索引",
                                语言 = 格式.language
                            )
                        )
                    }
                }
            }
        }
        return 结果
    }

    override fun 切换音轨(音轨: 音轨信息) {
        val 播放器实例 = 播放器 ?: return
        val 媒体轨道组 = 播放器实例.currentTracks.groups[音轨.组索引].mediaTrackGroup ?: return
        
        val 构建器 = 播放器实例.trackSelectionParameters
            .buildUpon()
            .setPreferredAudioLanguage(null)
            // 直接使用 setOverrideForType 设置覆盖
            .setOverrideForType(
                TrackSelectionOverride(
                    媒体轨道组,
                    listOf(音轨.轨索引)
                )
            )
        
        播放器实例.trackSelectionParameters = 构建器.build()
    }

    override fun 获取可用字幕(): List<字幕信息> {
        val 结果 = mutableListOf<字幕信息>()
        val 播放器实例 = 播放器 ?: return 结果
        val 轨道信息 = 播放器实例.currentTracks
        轨道信息.groups.forEachIndexed { 组索引, 分组 ->
            if (分组.type == C.TRACK_TYPE_TEXT) {
                分组.mediaTrackGroup?.let { 媒体分组 ->
                    for (轨索引 in 0 until 媒体分组.length) {
                        val 格式 = 媒体分组.getFormat(轨索引)
                        结果.add(
                            字幕信息(
                                组索引 = 组索引,
                                轨索引 = 轨索引,
                                标签 = 格式.label ?: 格式.language ?: "字幕$轨索引",
                                语言 = 格式.language
                            )
                        )
                    }
                }
            }
        }
        return 结果
    }

    override fun 切换字幕(字幕: 字幕信息?) {
        val 播放器实例 = 播放器 ?: return
        val 构建器 = 播放器实例.trackSelectionParameters.buildUpon()
        
        if (字幕 == null) {
            // 关闭字幕
            构建器.setTrackTypeDisabled(C.TRACK_TYPE_TEXT, true)
        } else {
            // 启用字幕并选择特定轨道
            构建器.setTrackTypeDisabled(C.TRACK_TYPE_TEXT, false)
            
            val 媒体轨道组 = 播放器实例.currentTracks.groups[字幕.组索引].mediaTrackGroup ?: return
            
            // 直接使用 setOverrideForType 设置覆盖
            构建器.setOverrideForType(
                TrackSelectionOverride(
                    媒体轨道组,
                    listOf(字幕.轨索引)
                )
            )
        }
        
        播放器实例.trackSelectionParameters = 构建器.build()
    }


}